﻿using System;
using System.Collections;
using System.Collections.Generic;

namespace ICommonLibrary.Collection {

    public class LockedDictionary<TKey, TValue> : IDictionary<TKey, TValue> {

        private readonly Dictionary<TKey, TValue> _dict = new Dictionary<TKey, TValue>();

        public void Add(TKey key, TValue value) {
            lock (_dict) {
                _dict.Add(key, value);
            }
        }

        public bool ContainsKey(TKey key) {
            return _dict.ContainsKey(key);
        }

        public ICollection<TKey> Keys {
            get {
                lock (_dict) {
                    return _dict.Keys;
                }
            }
        }

        public bool Remove(TKey key) {
            lock (_dict) {
                return _dict.Remove(key);
            }
        }

        public bool TryGetValue(TKey key, out TValue value) {
            lock (_dict) {
                return _dict.TryGetValue(key, out value);
            }
        }

        public ICollection<TValue> Values {
            get {
                lock (_dict) {
                    return _dict.Values;
                }
            }
        }

        public TValue this[TKey key] {
            get { return _dict[key]; }
            set {
                lock (_dict) {
                    _dict[key] = value;
                }
            }
        }

        public void Add(KeyValuePair<TKey, TValue> item) {
            lock (_dict) {
                ((ICollection<KeyValuePair<TKey, TValue>>) _dict).Add(item);
            }
        }

        public void Clear() {
            lock (_dict) {
                _dict.Clear();
            }
        }

        public bool Contains(KeyValuePair<TKey, TValue> item) {
            return ((ICollection<KeyValuePair<TKey,
                         TValue>>) _dict).Contains(item);
        }

        public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) {
            lock (_dict) {
                ((ICollection<KeyValuePair<TKey, TValue>>) _dict).CopyTo(array, arrayIndex);
            }
        }

        public int Count {
            get { return _dict.Count; }
        }

        public bool IsReadOnly {
            get { return false; }
        }

        public TValue GetValueAddIfNotExist(TKey key, Func<TValue> func) {
            lock (_dict) {
                TValue v;
                if (!TryGetValue(key, out v)) {
                    v = func();
                    this[key] = v;
                }
                return v;
            }
        }

        public bool Remove(KeyValuePair<TKey, TValue> item) {
            lock (_dict) {
                return ((ICollection<KeyValuePair<TKey, TValue>>) _dict).Remove(item);
            }
        }

        public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() {
            return _dict.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator() {
            return ((IEnumerable) _dict).GetEnumerator();
        }
    }
}